package com.tanhua.server.service;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.commons.key.RedisKeyConst;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.domain.db.PageResult;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mg.FollowUser;
import com.tanhua.domain.mg.Video;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.domain.vo.VideoVo;
import com.tanhua.dubbo.api.FollowUserApi;
import com.tanhua.dubbo.api.FriendApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.mg.VideoApi;
import com.tanhua.server.utils.ThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
@Slf4j
public class VideoService {
    //订阅VideoApi
    @Reference
    private VideoApi videoApi;
    //订阅userInfo
    @Reference
    private UserInfoApi userInfoApi;
    //订阅FollowUserApi
    @Reference
    private FollowUserApi followUserApi;
    //订阅FriendApi
    @Reference
    private FriendApi friendApi;
    //注入ossTemplate
    @Autowired
    private OssTemplate ossTemplate;
    //注入UserLikeNumService
    @Autowired
    private UserLikeNumService userLikeNumService;
   /* //创建一个客户端
    @Autowired
    private FastFileStorageClient fastFileStorageClient;
    @Autowired
    private FdfsWebServer fdfsWebServer;*/

   @Autowired
   private UserInfoService userInfoService;
    //注入ThreadLocalUtils
    @Autowired
    private ThreadLocalUtils threadUtils;
    //注入RedisTemplate
    @Autowired
    private RedisTemplate<String,String> redisTemplate;


    /**
     * 发布小视频
     */
    @CacheEvict(value = "videoList", allEntries = true)
    public void uploadVideo(MultipartFile videoThumbnail, MultipartFile videoFile) {
        log.debug("发布小视频，正在清除缓存");
        try {
            //获得当前用户的id
            Long userId = threadUtils.getUserId();
            String fdfsPicUrl= userInfoService.getUploadUrlByFdfs(videoThumbnail);
            String fdfsVideoUrl = userInfoService.getUploadUrlByFdfs(videoFile);
            log.debug("图片地址："+fdfsPicUrl);
            log.debug("视频地址："+fdfsVideoUrl);
            //创建Video对象 补全信息
            Video video = new Video();
            video.setPicUrl(fdfsPicUrl);//设置图片地址
            video.setVideoUrl(fdfsVideoUrl);//设置视频地址
            video.setUserId(userId);//设置用户id
            video.setText("佳人视频");
            //调用服务接口 保存数据
            videoApi.save(video);
        } catch (IOException e) {
            e.printStackTrace();
            throw new TanHuaException(ErrorResult.picUploadFailed());
        }
    }

    /**
     * 小视频列表
     */
    @Cacheable(value = "videoList", key = "#page + '_' +  #pagesize")
    public PageResult<VideoVo> findVideo(Integer page, Integer pagesize) {
        log.debug("正在从MongoDB数据库中执行查询小视频列表");
        //获取当前用户id
        Long currentUserId = threadUtils.getUserId();
        //service层 调用VideoApi 查询分页数据 返回PageResult<Video>分页数据
        PageResult<Video> videoPageResult=videoApi.queryVideoPage(page,pagesize);
        //获取videopageResult集合对象
        List<Video> videoList = videoPageResult.getItems();
        //创建一个集合 用于存储VideoVo对象
        List<VideoVo> videoVoList = new ArrayList<>();
        //遍历pageresult的itmes集合
        if(CollectionUtils.isNotEmpty(videoList)){
            for (Video video : videoList) {
                VideoVo videoVo = new VideoVo();
                //获取视频作者
                Long avatarId = video.getUserId();
                //根据video中的用户Id 查询userinfo表 返回userinfo
                UserInfo userInfo = userInfoApi.findUserInfoByID(avatarId);
                //复制userinfo和video的属性到vo属性
                BeanUtils.copyProperties(video,videoVo);
                BeanUtils.copyProperties(userInfo,videoVo);
                //单独进行赋值
                videoVo.setId(String.valueOf(video.getId()));//视频编号
                videoVo.setUserId(userInfo.getId().intValue());//用户id
                videoVo.setCover(video.getPicUrl());//封面
                videoVo.setSignature("这个人很懒 什么都没有写~");//签名
//                videoVo.setHasFocus(0);//关注的状态
                isHasFocus(currentUserId,videoVo);
//                videoVo.setHasLiked(0);//点赞状态
                isHasLiked(currentUserId,videoVo);
                //添加对象到集合
                videoVoList.add(videoVo);
            }
        }
        //创建PageResult<VideoVo>
        PageResult<VideoVo> videoVoPageResult = new PageResult<>();
        BeanUtils.copyProperties(videoPageResult,videoVoPageResult);
        videoVoPageResult.setItems(videoVoList);
        return videoVoPageResult;
    }
    /**
     * 关注作者
     */
    @CacheEvict(value = "videoList", allEntries = true)
    public void addFollowUserAndFriend(Long focusId) {
        //a.获取当前用户的id
        Long currentUserId = threadUtils.getUserId();
        //b.调用FollowUserApi的方法 在作者表添加关系
        //创建一个FollowUser对象
        FollowUser followUser = new FollowUser();
        followUser.setUserId(currentUserId);//设置当前用户id
        followUser.setFollowUserId(focusId);//设置视频作者id
        addFollowAndLikeIfHave(focusId,currentUserId,followUser);
        //创建一个存储关注状态的redis Key 前缀+当前用户Id+作者Id
        String key= RedisKeyConst.USER_FOCUS_STATUS+currentUserId+"_"+focusId;
        redisTemplate.opsForValue().set(key,"user_focus_status");
        log.debug("正在执行关注状态的redis缓存");
    }

    /**↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
     * 添加关系 如果是对方也关注了自己 添加好友关系
     * @param focusId
     * @param currentUserId
     * @param followUser
     */
     void addFollowAndLikeIfHave(Long focusId, Long currentUserId, FollowUser followUser) {
        //先判断关注的对象是否是自己 如果是自己 那么就提示关注成功 不插入数据
        if(currentUserId.equals(focusId)){
            log.debug("当前关注的对象是用户本人！");
            return;
        }
        //在插入数据之前先查询是否已经关注了该用户
        FollowUser focus = followUserApi.queryFollowUserByTwoId(followUser);
        if(focus==null){
            //如果表中不存在关系 那么就执行插入
            followUserApi.save(followUser);
        }
        //c.调用FollowUserApi的方法 查询作者表中 作者是否关注了当前的用户
        //创建一个对象 用于存储作者id 和当前好友id
        // （主要是为了查询作者表中作者是否关注了当前用户）
        FollowUser followUserIsExist = followUserApi.
                queryFollowUserByTwoId(new FollowUser(null,focusId,currentUserId,null));
        //d.判断 如果关注了当前的用户
        if (followUserIsExist!=null){
           /* //那么就在好友表中建立两者的关系
            friendApi.save(currentUserId,focusId);
            friendApi.save(focusId,currentUserId);*/
           //调用userLikeNumService的方法 添加好友的双向关系
            userLikeNumService.addTwoWayFriendship(currentUserId,focusId);
        }
    }

    /**
     * 取消关注
     */
    @CacheEvict(value = "videoList", allEntries = true)
    public void unFollowUserAndFriend(Long focusId) {
        //a.获取当前用户的id
        Long currentUserId = threadUtils.getUserId();
        //b.调用FollowUserApi的方法 在作者表添加关系
        //创建一个FollowUser对象
        FollowUser followUser = new FollowUser();
        followUser.setUserId(currentUserId);//设置当前用户id
        followUser.setFollowUserId(focusId);//设置视频作者id
        //在插入数据之前先查询是否已经关注了该用户
        FollowUser focus = followUserApi.queryFollowUserByTwoId(followUser);
        if(focus!=null){
            //如果表中存在关注关系 那么就执行删除
            followUserApi.remove(followUser);
            //删除好友关系
            friendApi.remove(currentUserId,focusId);
            friendApi.remove(focusId,currentUserId);
        }
        //创建一个存储关注状态的redis Key 前缀+当前用户Id+作者Id
        String key= RedisKeyConst.USER_FOCUS_STATUS+currentUserId+"_"+focusId;
        //删除redis
        redisTemplate.delete(key);
        log.debug("正在执行取消关注的redis删除");

    }
    /**
     * 小视频喜欢是否高亮显示的判断
     */
    public void isHasFocus(Long currentUserId,VideoVo videoVo) {
        String key= RedisKeyConst.USER_FOCUS_STATUS+currentUserId+"_"+videoVo.getUserId();
        //判断redis中是否存在这个喜欢的键
        if(!StringUtils.isEmpty(redisTemplate.opsForValue().get(key))){
            videoVo.setHasFocus(1);
        }
        else{
            videoVo.setHasFocus(0);
        }
    }

    /**
     * 小视频喜欢是否高亮显示的判断
     */
    public void isHasLiked(Long currentUserId,VideoVo videoVo) {
        String key= RedisKeyConst.VIDEO_LIKE_STATE+currentUserId+"_"+videoVo.getUserId();
        //判断redis中是否存在这个喜欢的键
        if(!StringUtils.isEmpty(redisTemplate.opsForValue().get(key))){
            videoVo.setHasLiked(1);
        }
        else{
            videoVo.setHasLiked(0);
        }
    }
}
